package com.wechat.service.account.rest;

import com.alibaba.fastjson.JSONObject;
import com.wechat.service.account.dto.customMenu.*;
import com.wechat.service.account.dto.messageManage.receiveCommonMessage.*;
import com.wechat.service.account.dto.messageManage.receiveEventPush.LocationEventRespDTO;
import com.wechat.service.account.dto.messageManage.receiveEventPush.ScanParamsQrcodeRespDTO;
import com.wechat.service.account.dto.messageManage.receiveEventPush.SubscribeOrNotRespDTO;
import com.wechat.service.account.dto.messageManage.templateMessage.TemplateMessageEventDTO;
import com.wechat.service.account.dto.wetchatAccess.WechatAccessReqDTO;
import com.wechat.service.account.service.HandleCommonMessageService;
import com.wechat.service.account.service.HandleEventPushService;
import com.wechat.service.account.service.HandleMenuEventService;
import com.wechat.service.account.service.HandleTemplateMessageEventService;
import com.wechat.service.account.util.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author： ygl
 * @date： 2019/07/10
 * @Description：
 * 接入微信公众平台开发
 * 开发者通过检验signature对请求进行校验（下面有校验方式）。可以在浏览器控制台查询参数
 * 若确认此次GET请求来自微信服务器，请原样返回echostr参数内容，则接入生效，成为开发者成功，否则接入失败。加密/校验流程如下：
 * 1）将token、timestamp、nonce三个参数进行字典序排序
 * 2）将三个参数字符串拼接成一个字符串进行sha1加密
 * 3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
 */
@Slf4j
@RestController
public class WechatAccessRest {

    /**
     * 接入微信公众平台开发时的验证
     * @param reqDTO
     * @return
     */
    @GetMapping("/wechat/access")
    public String access(WechatAccessReqDTO reqDTO){
        log.info("验证消息的确来自微信服务器:{}", JSONObject.toJSONString(reqDTO));
        return reqDTO.getEchostr();
    }

    @Autowired
    private HandleMenuEventService handleMenuEventService;

    @Autowired
    private HandleCommonMessageService handleCommonMessageService;

    @Autowired
    private HandleEventPushService handleEventPushService;

    @Autowired
    private HandleTemplateMessageEventService handleTemplateMessageEventService;

    /**
     * 接收菜单事件推送
     * @param
     * @return
     */
    @PostMapping("/wechat/access")
    public Object menuEvent(@RequestBody String pushXmlStr){
        log.info("接收菜单事件推送:{}", pushXmlStr);
        // 接收事件或者消息的类型
        String type = getEventMsgType(pushXmlStr);

        // ******************** 自定义菜单事件推送
        // 1. 点击菜单拉取消息时的事件推送
        if ("CLICK".equals(type)) {
            GetMessageEventReqDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, GetMessageEventReqDTO.class);
            return handleMenuEventService.handleGetMessageEvent(eventDTO);
            // 2. 点击菜单跳转链接时的事件推送
        } else if ("VIEW".equals(type)){
            JumpLinkEventReqDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, JumpLinkEventReqDTO.class);
            return handleMenuEventService.handleJumpLinkEvent(eventDTO);
            // 3. 扫码推事件的事件推送
        } else if ("scancode_push".equals(type)){
            ScanCodeEventReqDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, ScanCodeEventReqDTO.class);
            return handleMenuEventService.handleScanCodeEvent(eventDTO);
            // 4. 扫码推事件且弹出“消息接收中”提示框的事件推送
        } else if ("scancode_waitmsg".equals(type)){
            ScanCodeEventReqDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, ScanCodeEventReqDTO.class);
            return handleMenuEventService.handleScanCodeWaitMsgEvent(eventDTO);
            // 5. 弹出系统拍照发图的事件推送
        } else if ("pic_sysphoto".equals(type)){
            PicSysphotoEventReqDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, PicSysphotoEventReqDTO.class);
            return handleMenuEventService.handlePicSysphotoEvent(eventDTO);
            // 6. 弹出拍照或者相册发图的事件推送
        } else if ("pic_photo_or_album".equals(type)){
            PicSysphotoEventReqDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, PicSysphotoEventReqDTO.class);
            return handleMenuEventService.handlePicPhotoOrAlbumEvent(eventDTO);
            // 7. 弹出微信相册发图器的事件推送
        } else if ("pic_weixin".equals(type)){
            PicSysphotoEventReqDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, PicSysphotoEventReqDTO.class);
            return handleMenuEventService.handlePicWeixinEvent(eventDTO);
            // 8. 弹出地理位置选择器的事件推送
        } else if ("location_select".equals(type)){
            LocationSelectEventReqDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, LocationSelectEventReqDTO.class);
            return handleMenuEventService.handleLocationSelectEvent(eventDTO);
            // 9. 点击菜单跳转小程序的事件推送
        } else if ("view_miniprogram".equals(type)){
            MiniProgramEventReqDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, MiniProgramEventReqDTO.class);
            return handleMenuEventService.handleViewMiniProgramEvent(eventDTO);
        }
        // ******************** 接收普通消息
        // 1. 文本消息
        if ("text".equals(type)) {
            TextMessageRespDTO msgDTO = XmlUtil.xmlToBean(pushXmlStr, TextMessageRespDTO.class);
            return handleCommonMessageService.handleTextMessage(msgDTO);
            // 2. 图片消息
        } else if ("image".equals(type)){
            ImageMessageRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, ImageMessageRespDTO.class);
            return handleCommonMessageService.handleImageMessage(msgDTO);
            // 3. 语音消息
        } else if ("voice".equals(type)){
            VoiceMessageRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, VoiceMessageRespDTO.class);
            return handleCommonMessageService.handleVoiceMessage(msgDTO);
            // 4. 视频消息
        } else if ("video".equals(type)){
            VideoMessageRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, VideoMessageRespDTO.class);
            return handleCommonMessageService.handleVideoMessage(msgDTO);
            // 5. 小视频消息
        } else if ("shortvideo".equals(type)){
            VideoMessageRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, VideoMessageRespDTO.class);
            return handleCommonMessageService.handleShortVideoMessage(msgDTO);
            // 6. 地理位置消息
        } else if ("location".equals(type)){
            LocationMessageRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, LocationMessageRespDTO.class);
            return handleCommonMessageService.handleLocationMessage(msgDTO);
            // 7. 链接消息
        } else if ("link".equals(type)){
            LinkMessageRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, LinkMessageRespDTO.class);
            return handleCommonMessageService.handleLinkMessage(msgDTO);
        }

        // ******************** 接收事件推送
        // 1. 关注事件
        if ("subscribe".equals(type) && !pushXmlStr.contains("Ticket")) {
            SubscribeOrNotRespDTO msgDTO = XmlUtil.xmlToBean(pushXmlStr, SubscribeOrNotRespDTO.class);
            return handleEventPushService.handleSubscribeEvent(msgDTO);
            // 2. 取消关注事件
        } else if ("unsubscribe".equals(type)){
            SubscribeOrNotRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, SubscribeOrNotRespDTO.class);
            return handleEventPushService.handleUnSubscribeEvent(msgDTO);
            // 3. 扫描带参数二维码事件  进行关注后的事件推送
        } else if ("subscribe".equals(type) && pushXmlStr.contains("Ticket")){
            ScanParamsQrcodeRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, ScanParamsQrcodeRespDTO.class);
            return handleEventPushService.handleScanParamsQrcodeSubscribeEvent(msgDTO);
            // 4. 扫描带参数二维码事件  用户已关注时的事件推送
        } else if ("SCAN".equals(type)){
            ScanParamsQrcodeRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, ScanParamsQrcodeRespDTO.class);
            return handleEventPushService.handleScanParamsQrcodeSubscribedEvent(msgDTO);
            // 5. 上报地理位置事件
        } else if ("LOCATION".equals(type)){
            LocationEventRespDTO msgDTO  = XmlUtil.xmlToBean(pushXmlStr, LocationEventRespDTO.class);
            return handleEventPushService.handleLocationEvent(msgDTO);
            // 6. 点击菜单拉取消息时的事件推送
        } else if ("CLICK".equals(type)){
            log.info("同上述 自定义菜单事件推送－点击菜单拉取消息时的事件推送");
            // 7. 点击菜单跳转链接时的事件推送
        } else if ("VIEW".equals(type)){
            log.info("同上述 自定义菜单事件推送－点击菜单跳转链接时的事件推送");
        }

        // ******************** 模板消息 事件推送
        if("TEMPLATESENDJOBFINISH".equals(type)){
            TemplateMessageEventDTO eventDTO  = XmlUtil.xmlToBean(pushXmlStr, TemplateMessageEventDTO.class);
            handleTemplateMessageEventService.handleEvent(eventDTO);
        }
        return null;
    }

    /**
     * 获取事件或者消息的类型
     * @param xmlStr 事件推送xml字符串
     * @return
     */
    private String getEventMsgType(String xmlStr){
        // 获取事件的类型。如果没有获取消息的类型。
        int typeStart = xmlStr.indexOf("<Event>");
        int typeEnd = -1;
        if (typeStart > -1) {
            typeEnd = xmlStr.indexOf("</Event>");
        } else {
            typeStart = xmlStr.indexOf("<MsgType>");
            typeEnd = xmlStr.indexOf("</MsgType>");
        }
        String typeStr = xmlStr.substring(typeStart, typeEnd);
        int start = typeStr.lastIndexOf("[");
        int end = typeStr.indexOf("]]");
        String type = typeStr.substring(start+1, end);
        log.info("接收事件或者消息的类型:{}",type);
        return type;

    }
}
